﻿/****************************************************************************
 * Application   : Freekick Desktop Manager
 * Author        : sfreekick
 * Email         : sfreekick@gmail.com
 * Copyright     : (C) 2008 sfreekick
 * **************************************************************************/

/****************************************************************************
 *  This file is part of FreeKickManager.
 *
 *  FreeKickManager is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  FreeKickManager is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with FreeKickManager. If not, see <http://www.gnu.org/licenses/>.
 ****************************************************************************/

using System;
using System.Collections.Generic;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using System.IO;
using System.Net;

namespace FreeKickManager
{
    public partial class FrmEquipo : Form
    {
        private int idEquipo = 0;
        private string nombreEquipo = "";

        //ArrayList clasifSenior = null;
        //ArrayList clasifJuvenil = null;
        LinkedList<Partido> listaPartidos = null;

        public FrmEquipo()
        {
            InitializeComponent();

            idEquipo = 0;
            nombreEquipo = "";
        }

        public FrmEquipo(int idEquipo, string nombreEquipo)
        {
            InitializeComponent();

            this.idEquipo = idEquipo;
            this.nombreEquipo = nombreEquipo;

            lblNombreEquipo.Text = this.nombreEquipo;
            lblIdEquipo.Text = this.idEquipo.ToString();

            lblMensajeProgreso.Text = "Recuperando datos del equipo...";
            pbProgreso.Step = 1;
            pbProgreso.Minimum = 0;
            pbProgreso.Value = 1;
            pbProgreso.Maximum = 5;

            if (this.idEquipo.ToString().Equals(FrmPrincipal.opciones.obtenerOpcion("idEquipo")) && FrmPrincipal.listaPartidos != null)
                pbProgreso.Maximum -= 1;

            if (FrmPrincipal.clasifSenior != null)
                pbProgreso.Maximum -= 1;

            if (FrmPrincipal.clasifJuvenil != null)
                pbProgreso.Maximum -= 1;

            bworker.RunWorkerAsync();
        }

        private void cargarDatosEquipo(int idEquipo)
        {
            bool hayError = false;
            string liga = "";
            int divisionSenior = 0, divisionJuvenil = 0;
            int seriesSenior = 0, seriesJuvenil = 0;

            int temporadaActual = calcularTemporadaActual();

            hayError = !descargarXml(@"http://www.freekick.org/public/getdata.php?getdata=ownclub&datatype=xml&username=" + FrmPrincipal.opciones.obtenerOpcion("usuario") + "&password=" + FrmPrincipal.opciones.obtenerOpcion("password"), "temp\\equipo.xml");
            bworker.ReportProgress(1);

            if (!hayError)
            {
                XmlDocument doc = new XmlDocument();
                doc.Load("temp\\equipo.xml");

                //int id = Convert.ToInt32(doc.DocumentElement.GetAttribute("id"));
                //string nombreEquipo = doc.DocumentElement.SelectSingleNode("name").InnerText;
                //string nombreEstadio = doc.DocumentElement.SelectSingleNode("arena/name").InnerText;
                //int capacidadEstadio = Convert.ToInt32(doc.DocumentElement.SelectSingleNode("arena/total").InnerText);
                liga = doc.DocumentElement.SelectSingleNode("league").InnerText;
                divisionSenior = Convert.ToInt32(doc.DocumentElement.SelectSingleNode("senior/division").InnerText);
                seriesSenior = Convert.ToInt32(doc.DocumentElement.SelectSingleNode("senior/series").InnerText);
                divisionJuvenil = Convert.ToInt32(doc.DocumentElement.SelectSingleNode("youth/division").InnerText);
                seriesJuvenil = Convert.ToInt32(doc.DocumentElement.SelectSingleNode("youth/series").InnerText);
            }

            if (!hayError && (!this.idEquipo.ToString().Equals(FrmPrincipal.opciones.obtenerOpcion("idEquipo")) || FrmPrincipal.listaPartidos == null))
            {
                hayError = !descargarXml("http://www.freekick.org/public/getdata.php?getdata=matches&teamid=" + idEquipo + "&type=league", "temp\\partidos.xml");
                bworker.ReportProgress(1);

                if (!hayError)
                {
                    listaPartidos = filtrarPartidos("temp\\partidos.xml", temporadaActual);

                    FrmPrincipal.listaPartidos = listaPartidos;
                }
            }

            if (!hayError && FrmPrincipal.clasifSenior == null)
            {
                hayError = !descargarXml(@"http://www.freekick.org/public/getdata.php?getdata=league&datatype=xml&league=" + liga + "&division=" + divisionSenior + "&series=" + seriesSenior + "&squad=senior&season=" + temporadaActual, "temp\\clasifSenior.xml");
                bworker.ReportProgress(1);

                FrmPrincipal.clasifSenior = parsearClasificacion("temp\\clasifSenior.xml");
            }

            if (!hayError && FrmPrincipal.clasifJuvenil == null)
            {
                hayError = !descargarXml(@"http://www.freekick.org/public/getdata.php?getdata=league&datatype=xml&league=" + liga + "&division=" + divisionJuvenil + "&series=" + seriesJuvenil + "&squad=youth&season=" + temporadaActual, "temp\\clasifJuvenil.xml");
                bworker.ReportProgress(1);

                FrmPrincipal.clasifJuvenil = parsearClasificacion("temp\\clasifJuvenil.xml");
            }

            //if (!hayError && FrmPrincipal.clasifSenior == null)
            //{
            //    clasifSenior = calcularClasificacion(FrmPrincipal.listaPartidos, temporadaActual, "senior");

            //    FrmPrincipal.clasifSenior = clasifSenior;
            //}

            //if (!hayError && FrmPrincipal.clasifJuvenil == null)
            //{
            //    clasifJuvenil = calcularClasificacion(FrmPrincipal.listaPartidos, temporadaActual, "youth");

            //    FrmPrincipal.clasifJuvenil = clasifJuvenil;
            //}
        }

        private ArrayList parsearClasificacion(string xmlClasif)
        {
            ArrayList clasificacion = new ArrayList();

            XmlDocument doc = new XmlDocument();
            doc.Load(xmlClasif);

            XmlElement docNode = doc.DocumentElement;
            XmlNodeList listaNodos = docNode.SelectNodes("club");

            foreach (XmlNode equipo in listaNodos)
            {
                Equipo eq = new Equipo();

                eq.id = Convert.ToInt32(equipo.Attributes["id"].Value);
                eq.nombre = equipo.SelectSingleNode("name").InnerText;
                eq.ganados = Convert.ToInt32(equipo.SelectSingleNode("matches").Attributes["win"].Value);
                eq.empatados = Convert.ToInt32(equipo.SelectSingleNode("matches").Attributes["draw"].Value);
                eq.perdidos = Convert.ToInt32(equipo.SelectSingleNode("matches").Attributes["loss"].Value);
                eq.golesFavor = Convert.ToInt32(equipo.SelectSingleNode("aggregate").Attributes["for"].Value);
                eq.golesContra = Convert.ToInt32(equipo.SelectSingleNode("aggregate").Attributes["against"].Value);
                eq.puntos = Convert.ToInt32(equipo.SelectSingleNode("points").InnerText);

                clasificacion.Add(eq);
            }

            return clasificacion;
        }

        private ArrayList calcularClasificacion(LinkedList<Partido> listaPartidos, int temporadaActual, string categoria)
        {
            Dictionary<int, Equipo> equiposGrupo = new Dictionary<int, Equipo>();
            Dictionary<int, Partido> partidosGrupo = new Dictionary<int, Partido>();

            //Recopilamos todos los equipos del grupo
            equiposGrupo.Add(Convert.ToInt32(listaPartidos.First.Value.idPropio), new Equipo(Convert.ToInt32(listaPartidos.First.Value.idPropio), listaPartidos.First.Value.nombrePropio));

            foreach (Partido p in listaPartidos)
            {
                if (p.categoria.Equals(categoria))
                {
                    //Si no existe lo añadimos a la lista
                    if (!equiposGrupo.ContainsKey(Convert.ToInt32(p.idOponente)))
                        equiposGrupo.Add(Convert.ToInt32(p.idOponente), new Equipo(Convert.ToInt32(p.idOponente), p.nombreOponente));
                }
            }

            //Descargamos los partidos de cada equipo y recopilamos todos los partidos jugados del grupo
            foreach (int id in equiposGrupo.Keys)
            {
                Equipo eq = equiposGrupo[id];

                descargarXml("http://www.freekick.org/public/getdata.php?getdata=matches&teamid=" + id + "&type=league", "partidosGrupo.xml");

                LinkedList<Partido> lp = filtrarPartidos("partidosGrupo.xml", temporadaActual, categoria);

                foreach (Partido p in lp)
                {
                    if (!partidosGrupo.ContainsKey(Convert.ToInt32(p.id)))
                    {
                        if (p.jugado.Equals("true"))
                        {
                            partidosGrupo.Add(Convert.ToInt32(p.id), p);
                        }
                    }
                }

                bworker.ReportProgress(1);
            }

            //Recorremos la lista de partidos jugados para calcular los puntos de cada equipo
            foreach (Partido p in partidosGrupo.Values)
            {
                string[] resultado = p.resultado.Split(new string[1] { "-" }, StringSplitOptions.RemoveEmptyEntries);

                int idLocal = 0, idVisitante = 0;
                int golesLocal = 0, golesVisitante = 0;

                if(p.campo.Equals("home"))
                {
                    idLocal = Convert.ToInt32(p.idPropio);
                    idVisitante = Convert.ToInt32(p.idOponente);
                }
                else
                {
                    idLocal = Convert.ToInt32(p.idOponente);
                    idVisitante = Convert.ToInt32(p.idPropio);
                }

                golesLocal = Convert.ToInt32(resultado[0]);
                golesVisitante = Convert.ToInt32(resultado[1]);

                equiposGrupo[idLocal].golesFavor += golesLocal;
                equiposGrupo[idLocal].golesContra += golesVisitante;

                equiposGrupo[idVisitante].golesFavor += golesVisitante;
                equiposGrupo[idVisitante].golesContra += golesLocal;

                if (golesLocal > golesVisitante)
                {
                    equiposGrupo[idLocal].puntos += 3;
                    equiposGrupo[idLocal].ganados += 1;
                    equiposGrupo[idVisitante].perdidos += 1;
                }
                else if (golesLocal < golesVisitante)
                {
                    equiposGrupo[idVisitante].puntos += 3;
                    equiposGrupo[idVisitante].ganados += 1;
                    equiposGrupo[idLocal].perdidos += 1;
                }
                else
                {
                    equiposGrupo[idLocal].puntos += 1;
                    equiposGrupo[idVisitante].puntos += 1;

                    equiposGrupo[idLocal].empatados += 1;
                    equiposGrupo[idVisitante].empatados += 1;
                }
            }

            //Calculamos la clave de ordenacion para cada equipo
            ArrayList clasif = new ArrayList();
            foreach (int id in equiposGrupo.Keys)
            {
                Equipo eq = equiposGrupo[id];

                clasif.Add(eq);
            }

            clasif.Sort();
            clasif.Reverse();

            return clasif;
        }

        private void cargarListaPartidos(ListView list, LinkedList<Partido> listaPartidos, string categoria)
        {
            foreach (Partido p in listaPartidos)
            {
                if (p.categoria.Equals(categoria))
                {
                    ListViewItem li = new ListViewItem(new string[3] { 
                        p.campo.Equals("home") ? p.nombrePropio : p.nombreOponente, 
                        p.campo.Equals("home") ? p.nombreOponente : p.nombrePropio, 
                        p.resultado });

                    li.Tag = p;
                    list.Items.Add(li);
                }
            }   
        }

        private int calcularTemporadaActual()
        {
            DateTime fechaReferencia = new DateTime(2008, 1, 21);
            int temporadaReferencia = 16;

            DateTime hoy = DateTime.Now;

            DateTime fechaSiguienteTemporada = fechaReferencia.AddDays(98);
            int siguienteTemporada = temporadaReferencia + 1;

            while (fechaSiguienteTemporada < hoy)
            {
                fechaSiguienteTemporada = fechaSiguienteTemporada.AddDays(98);
                siguienteTemporada++;
            }

            return (siguienteTemporada-1);
        }

        private LinkedList<Partido> filtrarPartidos(string xmlPath, int temporada)
        {
            LinkedList<Partido> lista = new LinkedList<Partido>();

            XmlDocument doc = new XmlDocument();
            doc.Load(xmlPath);

            XmlNodeList listaNodos = doc.GetElementsByTagName("match");

            string temp = "";

            foreach (XmlNode nodoPartido in listaNodos)
            {
                temp = nodoPartido.SelectSingleNode("season").InnerText;

                if(temp.Equals(temporada.ToString()))
                {
                    Partido partido = new Partido();
                    partido.id = nodoPartido.Attributes["id"].Value;
                    partido.fecha = nodoPartido.SelectSingleNode("date").InnerText;
                    partido.competicion = nodoPartido.SelectSingleNode("type").InnerText;
                    partido.categoria = nodoPartido.SelectSingleNode("squad").InnerText;
                    partido.temporada = nodoPartido.SelectSingleNode("season").InnerText; ;

                    partido.idPropio = doc.GetElementsByTagName("team")[0].Attributes["id"].Value;
                    partido.nombrePropio = doc.GetElementsByTagName("team")[0].SelectSingleNode("name").InnerText;

                    partido.idOponente = nodoPartido.SelectSingleNode("opponent").Attributes["id"].Value;
                    partido.nombreOponente = nodoPartido.SelectSingleNode("opponent/name").InnerText;
                    partido.jugado = nodoPartido.SelectSingleNode("played").InnerText;
                    partido.campo = nodoPartido.SelectSingleNode("field").InnerText;

                    if (partido.jugado.Equals("true"))
                        partido.resultado = nodoPartido.SelectSingleNode("result/final").InnerText;

                    lista.AddLast(partido);
                }
            }

            return lista;
        }

        private LinkedList<Partido> filtrarPartidos(string xmlPath, int temporada, string categoria)
        {
            LinkedList<Partido> lista = new LinkedList<Partido>();

            XmlDocument doc = new XmlDocument();
            doc.Load(xmlPath);

            XmlNodeList listaNodos = doc.GetElementsByTagName("match");

            string temp = "";
            string cat = "";

            foreach (XmlNode nodoPartido in listaNodos)
            {
                temp = nodoPartido.SelectSingleNode("season").InnerText;
                cat = nodoPartido.SelectSingleNode("squad").InnerText;

                if (temp.Equals(temporada.ToString()) &&
                    cat.Equals(categoria))
                {
                    Partido partido = new Partido();
                    partido.id = nodoPartido.Attributes["id"].Value;
                    partido.fecha = nodoPartido.SelectSingleNode("date").InnerText;
                    partido.competicion = nodoPartido.SelectSingleNode("type").InnerText;
                    partido.categoria = nodoPartido.SelectSingleNode("squad").InnerText;
                    partido.temporada = nodoPartido.SelectSingleNode("season").InnerText; ;

                    partido.idPropio = doc.GetElementsByTagName("team")[0].Attributes["id"].Value;
                    partido.nombrePropio = doc.GetElementsByTagName("team")[0].SelectSingleNode("name").InnerText;

                    partido.idOponente = nodoPartido.SelectSingleNode("opponent").Attributes["id"].Value;
                    partido.nombreOponente = nodoPartido.SelectSingleNode("opponent/name").InnerText;
                    partido.jugado = nodoPartido.SelectSingleNode("played").InnerText;
                    partido.campo = nodoPartido.SelectSingleNode("field").InnerText;

                    if (partido.jugado.Equals("true"))
                        partido.resultado = nodoPartido.SelectSingleNode("result/final").InnerText;

                    lista.AddLast(partido);
                }
            }

            return lista;
        }

        private bool descargarXml(string url, string path)
        {
            bool res = true;

            try
            {
                StreamWriter sw = new StreamWriter(path, false, Encoding.UTF8, 8192);

                StringBuilder sb = new StringBuilder();

                byte[] buf = new byte[8192];

                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);

                if (FrmPrincipal.opciones.obtenerOpcion("usarProxy").Equals("1"))
                {
                    request.Proxy = new System.Net.WebProxy(FrmPrincipal.opciones.obtenerOpcion("proxyUrl") + ":" + FrmPrincipal.opciones.obtenerOpcion("proxyPuerto"), true);
                    request.Proxy.Credentials = new NetworkCredential(FrmPrincipal.opciones.obtenerOpcion("proxyUsuario"), FrmPrincipal.opciones.obtenerOpcion("proxyPassword"), FrmPrincipal.opciones.obtenerOpcion("proxyDominio"));
                }

                HttpWebResponse response = (HttpWebResponse)request.GetResponse();

                Stream resStream = response.GetResponseStream();

                string tempString = null;
                int count = 0;

                do
                {
                    count = resStream.Read(buf, 0, buf.Length);

                    if (count != 0)
                    {
                        tempString = Encoding.UTF8.GetString(buf, 0, count);

                        sb.Append(tempString);
                    }
                }
                while (count > 0);

                sw.Write(sb.ToString());

                sw.Close();
            }
            catch (Exception ex)
            {
                MessageBox.Show("Se ha producido un error en la descarga del fichero XML. Detalle del error:\n\n" + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);

                res = false;
            }

            return res;
        }

        private void bworker_DoWork(object sender, DoWorkEventArgs e)
        {
            cargarDatosEquipo(this.idEquipo);
        }

        private void bworker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            pbProgreso.PerformStep();
        }

        private void bworker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            cargarListaPartidos(lstPartidosSenior, FrmPrincipal.listaPartidos, "senior");
            cargarListaPartidos(lstPartidosJuvenil, FrmPrincipal.listaPartidos, "youth");

            for (int i = 0; i < FrmPrincipal.clasifSenior.Count; i++)
            {
                Equipo eq = (Equipo)FrmPrincipal.clasifSenior[i];

                ListViewItem li = new ListViewItem(new string[4] { (i + 1).ToString(), eq.nombre, eq.puntos.ToString(), (eq.golesFavor - eq.golesContra).ToString() });
                li.Tag = eq;
                lstClasificacionSenior.Items.Add(li);
            }

            for (int i = 0; i < FrmPrincipal.clasifJuvenil.Count; i++)
            {
                Equipo eq = (Equipo)FrmPrincipal.clasifJuvenil[i];

                ListViewItem li = new ListViewItem(new string[4] { (i + 1).ToString(), eq.nombre, eq.puntos.ToString(), (eq.golesFavor - eq.golesContra).ToString() });
                li.Tag = eq;
                lstClasificacionJuvenil.Items.Add(li);
            }

            lblMensajeProgreso.Text = "Datos recuperados correctamente.";
        }

        private void lstPartidosSenior_DoubleClick(object sender, EventArgs e)
        {
            Partido p = (Partido)lstPartidosSenior.SelectedItems[0].Tag;

            if (!p.resultado.Equals(""))
            {
                FrmBrowser frm = new FrmBrowser(p);
                frm.Show();
            }
            else
            {
                FrmAlineacion frm = new FrmAlineacion(TipoListaJugadores.SENIOR);
                frm.MdiParent = (FrmPrincipal)this.Parent;
                frm.Show();
            }
        }

        private void lstClasificacionSenior_DoubleClick(object sender, EventArgs e)
        {
            Equipo eq = (Equipo)lstClasificacionSenior.SelectedItems[0].Tag;
            FrmEquipo frm = new FrmEquipo(eq.id, eq.nombre);
            frm.Show();
        }

        private void lstClasificacionJuvenil_DoubleClick(object sender, EventArgs e)
        {
            Equipo eq = (Equipo)lstClasificacionJuvenil.SelectedItems[0].Tag;
            FrmEquipo frm = new FrmEquipo(eq.id, eq.nombre);
            frm.Show();
        }

        private void lstPartidosJuvenil_DoubleClick(object sender, EventArgs e)
        {
            Partido p = (Partido)lstPartidosJuvenil.SelectedItems[0].Tag;

            if (!p.resultado.Equals(""))
            {
                FrmBrowser frm = new FrmBrowser(p);
                frm.Show();
            }
            else
            {
                FrmAlineacion frm = new FrmAlineacion(TipoListaJugadores.JUNIOR);
                frm.MdiParent = (FrmPrincipal)this.Parent;
                frm.Show();
            }
        }
    }
}
